Rellenar
Rellenar
Rellenar
El conjunto de datos que hemos elegido está en la siguiente url: https://www.kaggle.com/fedesoriano/heart-failure-prediction. Se ha escogido ya que es una temática muy interesante las enfermedades cardiovasculares y al mismo tiempo comprobamos que haya campos numéricos y categóricos. Lo que pretende responder es como afecta o no las enfermedades cardiovasculares en función de las caracterísitcas de las personas.
Se lee el fichero “heart.csv”.
heart <- read.csv("heart.csv",sep=",")
A continuación, obtenemos el listado de variables:
str(heart)
## 'data.frame': 918 obs. of 12 variables:
## $ Age : int 40 49 37 48 54 39 45 54 37 48 ...
## $ Sex : chr "M" "F" "M" "F" ...
## $ ChestPainType : chr "ATA" "NAP" "ATA" "ASY" ...
## $ RestingBP : int 140 160 130 138 150 120 130 110 140 120 ...
## $ Cholesterol : int 289 180 283 214 195 339 237 208 207 284 ...
## $ FastingBS : int 0 0 0 0 0 0 0 0 0 0 ...
## $ RestingECG : chr "Normal" "Normal" "ST" "Normal" ...
## $ MaxHR : int 172 156 98 108 122 170 170 142 130 120 ...
## $ ExerciseAngina: chr "N" "N" "N" "Y" ...
## $ Oldpeak : num 0 1 0 1.5 0 0 0 0 1.5 0 ...
## $ ST_Slope : chr "Up" "Flat" "Up" "Flat" ...
## $ HeartDisease : int 0 1 0 1 0 0 0 0 1 0 ...
Se muestra un resumen de las variables.
summary(heart)
## Age Sex ChestPainType RestingBP
## Min. :28.00 Length:918 Length:918 Min. : 0.0
## 1st Qu.:47.00 Class :character Class :character 1st Qu.:120.0
## Median :54.00 Mode :character Mode :character Median :130.0
## Mean :53.51 Mean :132.4
## 3rd Qu.:60.00 3rd Qu.:140.0
## Max. :77.00 Max. :200.0
## Cholesterol FastingBS RestingECG MaxHR
## Min. : 0.0 Min. :0.0000 Length:918 Min. : 60.0
## 1st Qu.:173.2 1st Qu.:0.0000 Class :character 1st Qu.:120.0
## Median :223.0 Median :0.0000 Mode :character Median :138.0
## Mean :198.8 Mean :0.2331 Mean :136.8
## 3rd Qu.:267.0 3rd Qu.:0.0000 3rd Qu.:156.0
## Max. :603.0 Max. :1.0000 Max. :202.0
## ExerciseAngina Oldpeak ST_Slope HeartDisease
## Length:918 Min. :-2.6000 Length:918 Min. :0.0000
## Class :character 1st Qu.: 0.0000 Class :character 1st Qu.:0.0000
## Mode :character Median : 0.6000 Mode :character Median :1.0000
## Mean : 0.8874 Mean :0.5534
## 3rd Qu.: 1.5000 3rd Qu.:1.0000
## Max. : 6.2000 Max. :1.0000
A partir de esto, se puede concluir con que hay 12 variables y 918 observaciones. También se aprecia que en el dataset hay 3 tipos de datos:
Pasamos los valores int a numeric y los char a factor.
heart$Age <- as.numeric(heart$Age)
heart$Sex <- as.factor(heart$Sex)
heart$ChestPainType <- as.factor(heart$ChestPainType)
heart$RestingBP <- as.numeric(heart$RestingBP)
heart$Cholesterol <- as.numeric(heart$Cholesterol)
heart$FastingBS <- as.numeric(heart$FastingBS)
heart$RestingECG <- as.factor(heart$RestingECG)
heart$MaxHR <- as.numeric(heart$MaxHR)
heart$ExerciseAngina <- as.factor(heart$ExerciseAngina)
heart$ST_Slope <- as.factor(heart$ST_Slope)
heart$HeartDisease <- as.numeric(heart$HeartDisease)
En este apartado, se va a mostrar el diagrama de cajas de cada una de las variables numéricas para comprobar si hay posibles outliers.
Age:
Se aprecia que en la variable “Age” no hay ningún valor extremo.
boxplot(heart$Age,main="Edad del paciente")
boxplot.stats(heart$Age)$out
## numeric(0)
RestingBP:
En el campo “RestingBP” se observa algunos outliers, pero no se eliminarán debido a que la presión arterial sistólica puede tener valores superiores a 180 (esto sería una crisis de hipertensión).
boxplot(heart$RestingBP,main="Presión arterial en reposo")
boxplot.stats(heart$RestingBP)$out
## [1] 190 180 180 180 200 180 180 180 80 200 185 200 180 180 0 178 172 180 190
## [20] 174 178 180 200 192 178 180 180 172
Cholesterol:
En esta variable se aprecian una serie de valores extremos, pero por el contrario no es extraño ya que un colesterol de 603 se puede tener (https://www.tuotromedico.com/parametros/colesterol-en-sangre-alto.htm), aunque es un valor muy elevado. También se puede tener el valor 100 que es óptimo.
boxplot(heart$Cholesterol,main="Colesterol")
boxplot.stats(heart$Cholesterol)$out
## [1] 468 518 412 529 466 603 491 0 0 0 0 0 0 0 0 0 0 0
## [19] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [37] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [55] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [73] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [91] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [109] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [127] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [145] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [163] 0 0 0 0 0 0 0 0 0 0 0 458 0 0 0 0 0 0
## [181] 564 417 409
MaxHR :
Se puede apreciar que hay dos valores extremos: 60 y 63. Esas frecuencias cardíacas máximas son muy bajas y por tanto lo podemos detectar como valores extraños.
boxplot(heart$MaxHR,main="Frecuencia cardíaca máxima alcanzada")
boxplot.stats(heart$MaxHR)$out
## [1] 63 60
A continuación, sustituímos esos valores por NA y luego lo trataremos mediante Knn.
posMaxHR <- which(heart$MaxHR==60 | heart$MaxHR==63)
heart$MaxHR[posMaxHR] <- NA
Se aplica kNN para ponerle un valor en función de sus vecinos más cercanos.
library(VIM)
## Loading required package: colorspace
## Loading required package: grid
## VIM is ready to use.
## Suggestions and bug-reports can be submitted at: https://github.com/statistikat/VIM/issues
##
## Attaching package: 'VIM'
## The following object is masked from 'package:datasets':
##
## sleep
MaxHR_new <- kNN(heart,variable="MaxHR",dist_var =c("Age","Sex","ChestPainType","FastingBS","RestingECG","ExerciseAngina","ST_Slope","HeartDisease"),k=3)
MaxHR_new <- MaxHR_new$MaxHR
heart$MaxHR <- MaxHR_new
Se comprueba que en esa posición hay otro valor diferente.
heart$MaxHR[posMaxHR]
## [1] 144 150
Se aprecia que no hay ningun valor NA.
colSums(is.na(heart))
## Age Sex ChestPainType RestingBP Cholesterol
## 0 0 0 0 0
## FastingBS RestingECG MaxHR ExerciseAngina Oldpeak
## 0 0 0 0 0
## ST_Slope HeartDisease
## 0 0
A continuación, comprobaremos si algún campo tiene un valor 0.
colSums(heart == 0)
## Age Sex ChestPainType RestingBP Cholesterol
## 0 0 0 1 172
## FastingBS RestingECG MaxHR ExerciseAngina Oldpeak
## 704 0 0 0 368
## ST_Slope HeartDisease
## 0 410
Viendo esto, se puede decir que no tiene sentido que los campos RestingBP y Cholesterol tengan ceros. En este caso, podemos hablar de información perdida.
posRestingBP <- which(heart$RestingBP == 0)
posCholesterol <- which(heart$Cholesterol == 0)
heart$RestingBP[posRestingBP] <- NA
heart$Cholesterol[posCholesterol] <- NA
Para esos 0, hemos metido NA ya que es un valor desconocido y ahora miraremos mediante Knn como tratar esos datos.
Para solucionar estos valores perdidos, vamos a hacer uso de la función knn.
RestingBP_new <- kNN(heart,variable="RestingBP",dist_var =c("Age","Sex","ChestPainType","FastingBS","RestingECG","ExerciseAngina","ST_Slope","HeartDisease"),k=3)
RestingBP_new <- RestingBP_new$RestingBP
heart$RestingBP <- RestingBP_new
Cholesterol_new <- kNN(heart,variable="Cholesterol",dist_var =c("Age","Sex","ChestPainType","FastingBS","RestingECG","ExerciseAngina","ST_Slope","HeartDisease"),k=3)
Cholesterol_new <- Cholesterol_new$Cholesterol
heart$Cholesterol <- Cholesterol_new
Se comprueba que ya no hay valores pérdidos en esas posiciones:
heart$RestingBP[posRestingBP]
## [1] 135
heart$Cholesterol[posCholesterol]
## [1] 235 270 230 204 277 254 223 203 182 230 288 254 230 254 182 230 210 177
## [19] 230 223 223 217 267 218 230 203 254 218 203 294 210 203 237 192 203 204
## [37] 258 212 223 292 223 230 282 240 203 258 210 263 210 203 254 254 237 198
## [55] 254 219 237 254 228 223 230 228 282 231 267 193 233 309 226 228 230 231
## [73] 269 260 171 274 297 253 235 253 216 233 211 193 203 263 228 281 233 247
## [91] 282 216 260 315 266 224 203 206 219 254 237 213 254 272 277 230 220 263
## [109] 203 203 204 193 237 213 263 203 256 203 254 282 218 204 254 203 219 254
## [127] 281 297 254 277 220 220 212 203 219 213 203 203 277 285 233 237 252 207
## [145] 213 309 254 203 240 297 179 233 228 302 216 235 277 283 249 241 228 213
## [163] 211 226 235 291 210 223 211 245 276 245
Observamos que los valores NA fueron sustitídos por otros en función de las características de los demás atributos.
Finalmente, vemos que ya no hay ningun valor perdido.
colSums(is.na(heart))
## Age Sex ChestPainType RestingBP Cholesterol
## 0 0 0 0 0
## FastingBS RestingECG MaxHR ExerciseAngina Oldpeak
## 0 0 0 0 0
## ST_Slope HeartDisease
## 0 0
En este apartado, lo que vamos a hacer es normalizar el campo Age usando min-max. Se creará un nuevo campo llamado Age_nor y se añadirá al dataset.
Age_nor <- (2*(heart$Age-min(heart$Age))/(max(heart$Age)-min(heart$Age)))-1
heart <- cbind(heart,Age_nor)
Estos datos, están en el intervalo [-1,1]
min(heart$Age_nor)
## [1] -1
max(heart$Age_nor)
## [1] 1
En esta apartado, también usaremos la variable “Age” para discretizarla en diferentes rangos y se añadirá al dataset con el nombre Age_dis.
Age_dist <- cut(heart$Age, breaks = c(0,40,60,80), labels = c("(0-40]","(40,60]","(60,80]"))
heart <- cbind(heart,Age_dist)
Ahora, tenemos el dataset sin valores vacíos así como nuevas variables normalizadas y discretas.
Por lo tanto, se muestra un resumen del dataset en el cual podemos ver la media, moda, cuartiles y valores mínimos y máximos en el caso de variables numéricas. En el caso de los factores, podemos ver el número de ocurrencias que tiene dicho valor.
summary(heart)
## Age Sex ChestPainType RestingBP Cholesterol
## Min. :28.00 F:193 ASY:496 Min. : 80.0 Min. : 85
## 1st Qu.:47.00 M:725 ATA:173 1st Qu.:120.0 1st Qu.:209
## Median :54.00 NAP:203 Median :130.0 Median :235
## Mean :53.51 TA : 46 Mean :132.5 Mean :243
## 3rd Qu.:60.00 3rd Qu.:140.0 3rd Qu.:272
## Max. :77.00 Max. :200.0 Max. :603
## FastingBS RestingECG MaxHR ExerciseAngina Oldpeak
## Min. :0.0000 LVH :188 Min. : 67 N:547 Min. :-2.6000
## 1st Qu.:0.0000 Normal:552 1st Qu.:120 Y:371 1st Qu.: 0.0000
## Median :0.0000 ST :178 Median :138 Median : 0.6000
## Mean :0.2331 Mean :137 Mean : 0.8874
## 3rd Qu.:0.0000 3rd Qu.:156 3rd Qu.: 1.5000
## Max. :1.0000 Max. :202 Max. : 6.2000
## ST_Slope HeartDisease Age_nor Age_dist
## Down: 63 Min. :0.0000 Min. :-1.00000 (0-40] : 93
## Flat:460 1st Qu.:0.0000 1st Qu.:-0.22449 (40,60]:604
## Up :395 Median :1.0000 Median : 0.06122 (60,80]:221
## Mean :0.5534 Mean : 0.04126
## 3rd Qu.:1.0000 3rd Qu.: 0.30612
## Max. :1.0000 Max. : 1.00000
En este apartado, comprobaremos la normalidad de las variables numéricas, pero las que no son dicotómicas.
Age
qqnorm(heart$Age)
qqline(heart$Age)
A simple vista, se puede ver que los datos están por la recta menos por los lados y podríamos asumir normalidad. De todas formas comprobaremos esto con el test de shapiro y Lilliefors.
shapiro.test(heart$Age)
##
## Shapiro-Wilk normality test
##
## data: heart$Age
## W = 0.99101, p-value = 2.165e-05
library(nortest)
lillie.test(heart$Age)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: heart$Age
## D = 0.063161, p-value = 3.158e-09
Viendo ambos test, se puede apreciar que no sigue una distribucción normal la variable “Age”.
RestingBP
qqnorm(heart$RestingBP)
qqline(heart$RestingBP)
Tal como se aprecia, los valores no suelen estar en la recta y por lo tanto no sigue una distribucción normal.
Cholesterol
qqnorm(heart$Cholesterol)
qqline(heart$Cholesterol)
Se aprecia que bastantes puntos están muy por fuera de la recta. Con esto, concluímos que el campo Cholesterol no sigue una distribución normal.
MaxHR
qqnorm(heart$MaxHR)
qqline(heart$MaxHR)
Se observa que los puntos suelen seguir la recta, menos en algunos lados.
Para estar más seguros aplicamos los test de shapiro y Lilliefors.
shapiro.test(heart$MaxHR)
##
## Shapiro-Wilk normality test
##
## data: heart$MaxHR
## W = 0.99239, p-value = 0.0001178
lillie.test(heart$MaxHR)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: heart$MaxHR
## D = 0.047706, p-value = 4.03e-05
Según ambos test, la variable MaxHR no sigue una distribución normal.
Oldpeak
qqnorm(heart$Oldpeak)
qqline(heart$Oldpeak)
A simple vista, se observa que muchos puntos están fuera de la recta y con esto podemos decir que no sigue una distribución normal.
Age_nor
qqnorm(heart$Age_nor)
qqline(heart$Age_nor)
Se aprecia que muchos puntos siguen la recta ( similar a la variable Age sin normalizar ).
A continuación, aplicamos los siguientes test:
shapiro.test(heart$Age_nor)
##
## Shapiro-Wilk normality test
##
## data: heart$Age_nor
## W = 0.99101, p-value = 2.165e-05
lillie.test(heart$Age_nor)
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: heart$Age_nor
## D = 0.063161, p-value = 3.158e-09
Nos da la misma información que la variable Age. Por tanto, podemos decir que no sigue una distribución normal.
Dado que el tamaño de este dataset es >30, se puede decir por el teorema del límite central que las variables mencionadas anteriormente siguen una distribución normal.
Primero, calculamos dos variables para obtener el colesterol de hombres y mujeres.
colHom <- heart$Cholesterol[heart$Sex=="M"]
colMuj <- heart$Cholesterol[heart$Sex=="F"]
Como hipotesis nula, se quiere saber si el colesterol en mujeres es igual que en el de los hombres.
Como hipotesis alternativa se quiere saber si el colesterol en mujeres es mayor que en hombres.
\[
\left\{
\begin{array}{ll}
H_{0}: & \mu_M=\mu_H \\
H_{1}: & \mu_M>\mu_H
\end{array}
\right.\\
\ Hipótesis\ unilateral
\] Por el teorema del límite central, asumimos normalidad ya que tenemos una muestra con n>30. Esto, es un contraste de hipótesis de dos muestras independientes sobre la media (varianzas desconocidas). Es un test unilateral por la derecha.
Ahora, comprobamos la homocesdasticidad.
var.test(colMuj, colHom)
##
## F test to compare two variances
##
## data: colMuj and colHom
## F = 1.3623, num df = 192, denom df = 724, p-value = 0.005232
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
## 1.095376 1.719717
## sample estimates:
## ratio of variances
## 1.362271
Se observa que p-value < 0.05. Por tanto, las varianzas no son iguales.
A continuación, aplicamos el test de este contraste de hipótesis.
t.test( colMuj,colHom , var.equal=FALSE, alternative = "greater")
##
## Welch Two Sample t-test
##
## data: colMuj and colHom
## t = 3.4263, df = 271.62, p-value = 0.0003533
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
## 8.591104 Inf
## sample estimates:
## mean of x mean of y
## 256.0933 239.5172
Se aprecia, que p-value < 0.05. Por tanto, se rechaza la hipótesis nula y se acepta la alternativa de que las mujeres tiene más colesterol que los hombres.
Primero, calculamos dos variables para obtener las enfermades cardíacas de hombres y mujeres.
carHom <- heart$FastingBS[heart$Sex=="M" & heart$HeartDisease=="1"]
carMuj <- heart$FastingBS[heart$Sex=="F" & heart$HeartDisease=="1"]
Como hipotesis nula, se quiere saber si las enfermades cardíacas es igual en hombres que en mujeres.
Como hipotesis alternativa se quiere saber si las enfermades cardíacas es mayor en hombres que en mujeres.
\[ \left\{ \begin{array}{ll} H_{0}: & \mu_H=\mu_M \\ H_{1}: & \mu_H>\mu_M \end{array} \right.\\ \ Hipótesis\ unilateral \]
Por el teorema del límite central, asumimos normalidad ya que tenemos una muestra con n>30. Esto, es un contraste de hipótesis de dos muestras independientes sobre la media (varianzas desconocidas). Es un test unilateral por la derecha.
Ahora, comprobamos la homocesdasticidad.
var.test(carHom,carMuj)
##
## F test to compare two variances
##
## data: carHom and carMuj
## F = 1.0073, num df = 457, denom df = 49, p-value = 0.9818
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
## 0.6381553 1.4800765
## sample estimates:
## ratio of variances
## 1.007349
Se observa que p-value > 0.05. Por tanto, las varianzas son iguales.
A continuación, aplicamos el test de este contraste de hipótesis.
t.test( carHom,carMuj , var.equal=TRUE, alternative = "greater")
##
## Two Sample t-test
##
## data: carHom and carMuj
## t = 0.2307, df = 506, p-value = 0.4088
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
## -0.09979074 Inf
## sample estimates:
## mean of x mean of y
## 0.3362445 0.3200000
Se aprecia, que p-value > 0.05. Por tanto, se acepta la hipótesis nula de que los hombres con enfermedad cardíaca tienen igual azucar en sangre que las mujeres con enfermedad cardíaca.
En este apartado, representaremos la matriz de correlación del dataset.
Pasamos todsas las variables a numéricas en un dataset nuevo.
heart_num <-heart[1:12]
heart_num$Sex <- as.numeric(heart_num$Sex)
heart_num$ChestPainType <- as.numeric(heart_num$ChestPainType)
heart_num$RestingECG <- as.numeric(heart_num$RestingECG)
heart_num$ExerciseAngina <- as.numeric(heart_num$ExerciseAngina)
heart_num$ST_Slope <- as.numeric(heart_num$ST_Slope)
Calculamos la correlación de las variables usando el método de pearson.
Corelacion <- cor(heart_num,method="pearson")
Corelacion
## Age Sex ChestPainType RestingBP
## Age 1.000000000 0.055750099 -0.07715013 0.263101716
## Sex 0.055750099 1.000000000 -0.12655877 0.009502133
## ChestPainType -0.077150132 -0.126558765 1.00000000 -0.010820389
## RestingBP 0.263101716 0.009502133 -0.01082039 1.000000000
## Cholesterol 0.035949480 -0.122833668 -0.07645522 0.092483840
## FastingBS 0.198039066 0.120075988 -0.07315099 0.067728664
## RestingECG -0.007484033 0.071552184 -0.07253685 0.023456877
## MaxHR -0.384306668 -0.187173215 0.28583652 -0.108506017
## ExerciseAngina 0.215792691 0.190664102 -0.35472729 0.152883307
## Oldpeak 0.258611536 0.105733537 -0.17737737 0.174304136
## ST_Slope -0.268263994 -0.150692544 0.21352120 -0.082226847
## HeartDisease 0.282038506 0.305444916 -0.38682769 0.118070714
## Cholesterol FastingBS RestingECG MaxHR
## Age 0.035949480 0.19803907 -0.007484033 -0.384306668
## Sex -0.122833668 0.12007599 0.071552184 -0.187173215
## ChestPainType -0.076455221 -0.07315099 -0.072536854 0.285836516
## RestingBP 0.092483840 0.06772866 0.023456877 -0.108506017
## Cholesterol 1.000000000 0.01262851 -0.091593724 -0.005341853
## FastingBS 0.012628509 1.00000000 0.087049561 -0.136763624
## RestingECG -0.091593724 0.08704956 1.000000000 -0.180854165
## MaxHR -0.005341853 -0.13676362 -0.180854165 1.000000000
## ExerciseAngina 0.090879090 0.06045067 0.077500389 -0.372902545
## Oldpeak 0.048075140 0.05269786 -0.020437522 -0.166729389
## ST_Slope -0.061766760 -0.17577434 -0.006778212 0.348051929
## HeartDisease 0.083198713 0.26729119 0.057384357 -0.397592228
## ExerciseAngina Oldpeak ST_Slope HeartDisease
## Age 0.21579269 0.25861154 -0.268263994 0.28203851
## Sex 0.19066410 0.10573354 -0.150692544 0.30544492
## ChestPainType -0.35472729 -0.17737737 0.213521201 -0.38682769
## RestingBP 0.15288331 0.17430414 -0.082226847 0.11807071
## Cholesterol 0.09087909 0.04807514 -0.061766760 0.08319871
## FastingBS 0.06045067 0.05269786 -0.175774343 0.26729119
## RestingECG 0.07750039 -0.02043752 -0.006778212 0.05738436
## MaxHR -0.37290255 -0.16672939 0.348051929 -0.39759223
## ExerciseAngina 1.00000000 0.40875250 -0.428705943 0.49428199
## Oldpeak 0.40875250 1.00000000 -0.501921270 0.40395072
## ST_Slope -0.42870594 -0.50192127 1.000000000 -0.55877071
## HeartDisease 0.49428199 0.40395072 -0.558770715 1.00000000
A continuación, representamos la matriz de correlación.
if (!require('corrplot')) install.packages('corrplot'); library('corrplot')
## Loading required package: corrplot
## corrplot 0.84 loaded
corrplot(Corelacion, method = "number")
Se calcula un modelo de regresión lineal simple cuya variable dependiente es MaxHR y independiente es Age.
Model_reg_sim <- lm(MaxHR~Age,data=heart)
summary(Model_reg_sim)
##
## Call:
## lm(formula = MaxHR ~ Age, data = heart)
##
## Residuals:
## Min 1Q Median 3Q Max
## -70.879 -15.933 0.938 18.066 58.507
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 191.97996 4.43148 43.32 <2e-16 ***
## Age -1.02754 0.08156 -12.60 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.3 on 916 degrees of freedom
## Multiple R-squared: 0.1477, Adjusted R-squared: 0.1468
## F-statistic: 158.7 on 1 and 916 DF, p-value: < 2.2e-16
Se observa que el coeficiente de determianción ajustado es bajo: 14.6%.
Se crea un modelo de regresión lineal múltiple con la variable dependiente MaxHR y indpendientes:HeartDisease, ST_Slope, FastingBS, Oldpeak, RestingECG, Sex, Cholesterol.
Model_reg_mul <- lm(MaxHR~Age+HeartDisease+ST_Slope+FastingBS+Oldpeak+RestingECG+Sex+Cholesterol,data=heart)
summary(Model_reg_mul)
##
## Call:
## lm(formula = MaxHR ~ Age + HeartDisease + ST_Slope + FastingBS +
## Oldpeak + RestingECG + Sex + Cholesterol, data = heart)
##
## Residuals:
## Min 1Q Median 3Q Max
## -75.52 -13.35 0.41 15.35 57.48
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 192.189947 6.728604 28.563 < 2e-16 ***
## Age -0.837303 0.080857 -10.355 < 2e-16 ***
## HeartDisease -9.084096 1.961702 -4.631 4.18e-06 ***
## ST_SlopeFlat -1.535571 2.962891 -0.518 0.60440
## ST_SlopeUp 10.238561 3.298723 3.104 0.00197 **
## FastingBS 1.342525 1.749232 0.767 0.44299
## Oldpeak 1.944141 0.782412 2.485 0.01314 *
## RestingECGNormal -9.617849 1.827829 -5.262 1.78e-07 ***
## RestingECGST -12.942031 2.234606 -5.792 9.60e-09 ***
## SexM -4.964359 1.826623 -2.718 0.00670 **
## Cholesterol 0.004842 0.012963 0.374 0.70883
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 21.13 on 907 degrees of freedom
## Multiple R-squared: 0.3057, Adjusted R-squared: 0.2981
## F-statistic: 39.94 on 10 and 907 DF, p-value: < 2.2e-16
Se aprecia un coeficiente de determinación bajo (30%).
Vamos a crear una regresión logística simple como variable dependiente HeartDisease y indpendiente MaxHR.
model_logis1 <- glm(formula=HeartDisease~MaxHR,data=heart,family=binomial())
summary(model_logis1)
##
## Call:
## glm(formula = HeartDisease ~ MaxHR, family = binomial(), data = heart)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.3785 -1.0261 0.5797 0.9631 2.0105
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 5.312314 0.462283 11.49 <2e-16 ***
## MaxHR -0.036878 0.003277 -11.25 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1262.1 on 917 degrees of freedom
## Residual deviance: 1105.8 on 916 degrees of freedom
## AIC: 1109.8
##
## Number of Fisher Scoring iterations: 4
Calculamos la bondad de ajuste usando el test de hoslem.
if (!require('ResourceSelection')) install.packages('ResourceSelection'); library('ResourceSelection')
## Loading required package: ResourceSelection
## ResourceSelection 0.3-5 2019-07-22
hoslem.test(heart$HeartDisease,fitted(model_logis1))
##
## Hosmer and Lemeshow goodness of fit (GOF) test
##
## data: heart$HeartDisease, fitted(model_logis1)
## X-squared = 15.098, df = 8, p-value = 0.05726
Se observa que p-value >0.05. Por tanto, el modelo ajusta bien los datos.
Calculamos una regresión logística múltiple con HeartDisease como variable dependiente y ST_Slope, Oldpeak, MaxHR, ChestPainType, RestingBP, Age_nor como variables dependientes
model_logis2 <- glm(formula=HeartDisease~ST_Slope+Oldpeak+MaxHR+ChestPainType+RestingBP+Age_nor,data=heart,family=binomial())
summary(model_logis2)
##
## Call:
## glm(formula = HeartDisease ~ ST_Slope + Oldpeak + MaxHR + ChestPainType +
## RestingBP + Age_nor, family = binomial(), data = heart)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.6439 -0.4265 0.2657 0.4951 2.5609
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.310735 0.987247 2.341 0.019254 *
## ST_SlopeFlat 0.900785 0.396679 2.271 0.023158 *
## ST_SlopeUp -1.417499 0.413301 -3.430 0.000604 ***
## Oldpeak 0.422374 0.108012 3.910 9.21e-05 ***
## MaxHR -0.013499 0.004404 -3.065 0.002175 **
## ChestPainTypeATA -2.288611 0.296705 -7.713 1.22e-14 ***
## ChestPainTypeNAP -1.778255 0.233869 -7.604 2.88e-14 ***
## ChestPainTypeTA -1.593164 0.393194 -4.052 5.08e-05 ***
## RestingBP 0.003921 0.005694 0.689 0.490997
## Age_nor 0.556923 0.290248 1.919 0.055012 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1262.14 on 917 degrees of freedom
## Residual deviance: 695.39 on 908 degrees of freedom
## AIC: 715.39
##
## Number of Fisher Scoring iterations: 5
Se aprecia que el AIC es mucho menor y por tanto, el modelo es mejor.
Calculamos la bondad de ajuste:
hoslem.test(heart$HeartDisease,fitted(model_logis2))
##
## Hosmer and Lemeshow goodness of fit (GOF) test
##
## data: heart$HeartDisease, fitted(model_logis2)
## X-squared = 12.797, df = 8, p-value = 0.119
Se aprecia que el modelo tiene p-value > 0.05. Por tanto, ajusta bien los datos.
head(heart)
## Age Sex ChestPainType RestingBP Cholesterol FastingBS RestingECG MaxHR
## 1 40 M ATA 140 289 0 Normal 172
## 2 49 F NAP 160 180 0 Normal 156
## 3 37 M ATA 130 283 0 ST 98
## 4 48 F ASY 138 214 0 Normal 108
## 5 54 M NAP 150 195 0 Normal 122
## 6 39 M NAP 120 339 0 Normal 170
## ExerciseAngina Oldpeak ST_Slope HeartDisease Age_nor Age_dist
## 1 N 0.0 Up 0 -0.51020408 (0-40]
## 2 N 1.0 Flat 1 -0.14285714 (40,60]
## 3 N 0.0 Up 0 -0.63265306 (0-40]
## 4 Y 1.5 Flat 1 -0.18367347 (40,60]
## 5 N 0.0 Up 0 0.06122449 (40,60]
## 6 N 0.0 Up 0 -0.55102041 (0-40]
Nos interesa desordenar los datos para poder elegir registros aleatorios. Guardaremos los datos con el nuevo nombre de: heart_clasification
set.seed(1)
heart_clasification <- heart[sample(nrow(heart)),]
Para la futura evaluación del árbol de decisión, es necesario dividir el conjunto de datos en un conjunto de entrenamiento y un conjunto de prueba. El conjunto de entrenamiento es el subconjunto del conjunto original de datos utilizado para construir un primer modelo; y el conjunto de prueba, el subconjunto del conjunto original de datos utilizado para evaluar la calidad del modelo.
Lo más correcto será utilizar un conjunto de datos diferente del que utilizamos para construir el árbol, es decir, un conjunto diferente del de entrenamiento. No hay ninguna proporción fijada con respecto al número relativo de componentes de cada subconjunto, pero la más utilizada acostumbra a ser 2/3 para el conjunto de entrenamiento y 1/3, para el conjunto de prueba.
La variable por la que clasificaremos es HeartDisease, para clasificar si existe riesgo de enfermedad cardíaca o no, y que se sitúa en nuestro en la columna, la 16. De esta forma, tendremos un conjunto de datos para el entrenamiento y uno para la validación
set.seed(666)
y <- heart_clasification[,12]
X <- heart_clasification[,1:11]
Dividimos el dataset en dos partes diferenciadas, train y test. Podemos crear directamente un rango utilizando el parámetro split_prop
split_prop <- 3
indexes = sample(1:nrow( heart_clasification), size=floor(((split_prop-1)/split_prop)*nrow(heart_clasification)))
trainx<-X[indexes,]
trainy<-y[indexes]
testx<-X[-indexes,]
testy<-y[-indexes]
if(!require(ggplot2)){
install.packages('ggplot2', repos='http://cran.us.r-project.org')
library(ggplot2)
}
## Loading required package: ggplot2
if(!require(ggpubr)){
install.packages('ggpubr', repos='http://cran.us.r-project.org')
library(ggpubr)
}
## Loading required package: ggpubr
if(!require(grid)){
install.packages('grid', repos='http://cran.us.r-project.org')
library(grid)
}
if(!require(gridExtra)){
install.packages('gridExtra', repos='http://cran.us.r-project.org')
library(gridExtra)
}
## Loading required package: gridExtra
if(!require(C50)){
install.packages('C50', repos='http://cran.us.r-project.org')
library(C50)
}
## Loading required package: C50
library("rpart")
library("rpart.plot")
Se crea el árbol de decisión usando los datos de entrenamiento:
Utilizaremos dos bibliotecas diferentes, una de ellas es rpart, para crear el árbol de decisión y rpart.plot para representar visualmente nuestro árbol de decisión.
modelo_clasificacion_rpart <- rpart(formula = trainy ~ ., data = trainx, method = "class" )
summary(modelo_clasificacion_rpart)
## Call:
## rpart(formula = trainy ~ ., data = trainx, method = "class")
## n= 612
##
## CP nsplit rel error xerror xstd
## 1 0.61433447 0 1.0000000 1.0000000 0.04217798
## 2 0.02559727 1 0.3856655 0.3856655 0.03276017
## 3 0.02389078 3 0.3344710 0.4061433 0.03341593
## 4 0.01365188 5 0.2866894 0.3412969 0.03121703
## 5 0.01000000 7 0.2593857 0.3276451 0.03070557
##
## Variable importance
## ST_Slope Oldpeak ChestPainType ExerciseAngina MaxHR
## 30 18 16 13 13
## Age Sex Cholesterol RestingBP
## 6 2 1 1
##
## Node number 1: 612 observations, complexity param=0.6143345
## predicted class=1 expected loss=0.4787582 P(node) =1
## class counts: 293 319
## probabilities: 0.479 0.521
## left son=2 (272 obs) right son=3 (340 obs)
## Primary splits:
## ST_Slope splits as RRL, improve=121.41240, (0 missing)
## ChestPainType splits as RLLL, improve= 90.58827, (0 missing)
## ExerciseAngina splits as LR, improve= 80.19091, (0 missing)
## Oldpeak < 0.45 to the left, improve= 53.26917, (0 missing)
## MaxHR < 150.5 to the right, improve= 47.53931, (0 missing)
## Surrogate splits:
## Oldpeak < 0.35 to the left, agree=0.775, adj=0.493, (0 split)
## ExerciseAngina splits as LR, agree=0.717, adj=0.364, (0 split)
## ChestPainType splits as RLLL, agree=0.699, adj=0.324, (0 split)
## MaxHR < 152.5 to the right, agree=0.686, adj=0.294, (0 split)
## Age < 54.5 to the left, agree=0.629, adj=0.165, (0 split)
##
## Node number 2: 272 observations, complexity param=0.02559727
## predicted class=0 expected loss=0.1691176 P(node) =0.4444444
## class counts: 226 46
## probabilities: 0.831 0.169
## left son=4 (185 obs) right son=5 (87 obs)
## Primary splits:
## ChestPainType splits as RLLL, improve=16.788120, (0 missing)
## Oldpeak < 0.45 to the left, improve=11.881400, (0 missing)
## ExerciseAngina splits as LR, improve= 9.085244, (0 missing)
## FastingBS < 0.5 to the left, improve= 6.480573, (0 missing)
## Age < 55.5 to the left, improve= 5.507843, (0 missing)
## Surrogate splits:
## ExerciseAngina splits as LR, agree=0.739, adj=0.184, (0 split)
## MaxHR < 112.5 to the right, agree=0.695, adj=0.046, (0 split)
## Oldpeak < 0.85 to the left, agree=0.691, adj=0.034, (0 split)
## Cholesterol < 348 to the left, agree=0.688, adj=0.023, (0 split)
##
## Node number 3: 340 observations, complexity param=0.02389078
## predicted class=1 expected loss=0.1970588 P(node) =0.5555556
## class counts: 67 273
## probabilities: 0.197 0.803
## left son=6 (58 obs) right son=7 (282 obs)
## Primary splits:
## MaxHR < 150.5 to the right, improve=15.923540, (0 missing)
## ChestPainType splits as RLLL, improve=15.109280, (0 missing)
## Sex splits as LR, improve=13.255020, (0 missing)
## ExerciseAngina splits as LR, improve= 9.783180, (0 missing)
## RestingBP < 130.5 to the left, improve= 4.033701, (0 missing)
##
## Node number 4: 185 observations
## predicted class=0 expected loss=0.04864865 P(node) =0.3022876
## class counts: 176 9
## probabilities: 0.951 0.049
##
## Node number 5: 87 observations, complexity param=0.02559727
## predicted class=0 expected loss=0.4252874 P(node) =0.1421569
## class counts: 50 37
## probabilities: 0.575 0.425
## left son=10 (58 obs) right son=11 (29 obs)
## Primary splits:
## Oldpeak < 0.45 to the left, improve=9.666667, (0 missing)
## FastingBS < 0.5 to the left, improve=6.448240, (0 missing)
## ExerciseAngina splits as LR, improve=5.287878, (0 missing)
## RestingBP < 127 to the right, improve=3.823607, (0 missing)
## Age < 57.5 to the left, improve=3.321839, (0 missing)
## Surrogate splits:
## Age < 60.5 to the left, agree=0.724, adj=0.172, (0 split)
## FastingBS < 0.5 to the left, agree=0.701, adj=0.103, (0 split)
## ExerciseAngina splits as LR, agree=0.690, adj=0.069, (0 split)
##
## Node number 6: 58 observations, complexity param=0.02389078
## predicted class=0 expected loss=0.4655172 P(node) =0.09477124
## class counts: 31 27
## probabilities: 0.534 0.466
## left son=12 (28 obs) right son=13 (30 obs)
## Primary splits:
## ChestPainType splits as RLLR, improve=5.028736, (0 missing)
## Cholesterol < 252 to the left, improve=4.087875, (0 missing)
## Oldpeak < 0.3 to the right, improve=2.702825, (0 missing)
## FastingBS < 0.5 to the left, improve=2.177545, (0 missing)
## RestingECG splits as LRR, improve=1.980081, (0 missing)
## Surrogate splits:
## Cholesterol < 252 to the left, agree=0.741, adj=0.464, (0 split)
## RestingBP < 136.5 to the left, agree=0.638, adj=0.250, (0 split)
## Oldpeak < 0.75 to the right, agree=0.638, adj=0.250, (0 split)
## Age < 58.5 to the left, agree=0.603, adj=0.179, (0 split)
## Sex splits as LR, agree=0.603, adj=0.179, (0 split)
##
## Node number 7: 282 observations, complexity param=0.01365188
## predicted class=1 expected loss=0.1276596 P(node) =0.4607843
## class counts: 36 246
## probabilities: 0.128 0.872
## left son=14 (36 obs) right son=15 (246 obs)
## Primary splits:
## Sex splits as LR, improve=8.282765, (0 missing)
## ExerciseAngina splits as LR, improve=3.716003, (0 missing)
## ChestPainType splits as RLLL, improve=3.550889, (0 missing)
## Oldpeak < 0.15 to the right, improve=2.227013, (0 missing)
## RestingBP < 132.5 to the left, improve=1.994501, (0 missing)
##
## Node number 10: 58 observations
## predicted class=0 expected loss=0.2586207 P(node) =0.09477124
## class counts: 43 15
## probabilities: 0.741 0.259
##
## Node number 11: 29 observations
## predicted class=1 expected loss=0.2413793 P(node) =0.04738562
## class counts: 7 22
## probabilities: 0.241 0.759
##
## Node number 12: 28 observations
## predicted class=0 expected loss=0.25 P(node) =0.04575163
## class counts: 21 7
## probabilities: 0.750 0.250
##
## Node number 13: 30 observations
## predicted class=1 expected loss=0.3333333 P(node) =0.04901961
## class counts: 10 20
## probabilities: 0.333 0.667
##
## Node number 14: 36 observations, complexity param=0.01365188
## predicted class=1 expected loss=0.4444444 P(node) =0.05882353
## class counts: 16 20
## probabilities: 0.444 0.556
## left son=28 (16 obs) right son=29 (20 obs)
## Primary splits:
## ExerciseAngina splits as LR, improve=5.377778, (0 missing)
## Oldpeak < 0.25 to the right, improve=3.432950, (0 missing)
## RestingBP < 134 to the left, improve=2.818025, (0 missing)
## ChestPainType splits as RLLR, improve=1.808547, (0 missing)
## MaxHR < 133.5 to the left, improve=1.455796, (0 missing)
## Surrogate splits:
## ChestPainType splits as RLLL, agree=0.722, adj=0.375, (0 split)
## Cholesterol < 273.5 to the left, agree=0.694, adj=0.312, (0 split)
## Age < 61.5 to the right, agree=0.667, adj=0.250, (0 split)
## RestingECG splits as LRR, agree=0.667, adj=0.250, (0 split)
## RestingBP < 122 to the left, agree=0.639, adj=0.187, (0 split)
##
## Node number 15: 246 observations
## predicted class=1 expected loss=0.08130081 P(node) =0.4019608
## class counts: 20 226
## probabilities: 0.081 0.919
##
## Node number 28: 16 observations
## predicted class=0 expected loss=0.25 P(node) =0.02614379
## class counts: 12 4
## probabilities: 0.750 0.250
##
## Node number 29: 20 observations
## predicted class=1 expected loss=0.2 P(node) =0.03267974
## class counts: 4 16
## probabilities: 0.200 0.800
Vamos a representar gráficamente el arbol obtenido de dos maneras diferentes:
rpart.plot(modelo_clasificacion_rpart, type=2,extra = 2, under = TRUE, faclen=5,cex=.55)
rpart.plot(modelo_clasificacion_rpart, type=2,extra = 8, under = TRUE, faclen=5,cex=.55)
En el primer árbol Observamos las tasas de clasificación para cada nodo, expresada como el número de clasificaciones correctas y el número de observaciones en el nodo. En el segundo gráfico observamos la probabilidad por cada clase.
predicted_model <- predict( modelo_clasificacion_rpart, testx, type="class" )
print(sprintf("La precisión del modelo4 es: %.4f %%",100*sum(predicted_model == testy) / length(predicted_model)))
## [1] "La precisión del modelo4 es: 83.6601 %"
Vamos a crear la matriz de confusión
mat_conf<-table(testy,Predicted=predicted_model)
mat_conf
## Predicted
## testy 0 1
## 0 98 19
## 1 31 158
if(!require(gmodels)){
install.packages('gmodels', repos='http://cran.us.r-project.org')
library(gmodels)
}
## Loading required package: gmodels
CrossTable(testy, predicted_model,prop.chisq = FALSE, prop.c = FALSE, prop.r =FALSE,dnn = c('Reality', 'Prediction'))
##
##
## Cell Contents
## |-------------------------|
## | N |
## | N / Table Total |
## |-------------------------|
##
##
## Total Observations in Table: 306
##
##
## | Prediction
## Reality | 0 | 1 | Row Total |
## -------------|-----------|-----------|-----------|
## 0 | 98 | 19 | 117 |
## | 0.320 | 0.062 | |
## -------------|-----------|-----------|-----------|
## 1 | 31 | 158 | 189 |
## | 0.101 | 0.516 | |
## -------------|-----------|-----------|-----------|
## Column Total | 129 | 177 | 306 |
## -------------|-----------|-----------|-----------|
##
##
añadir: DISCRETIZAR MÁS VARIABLES, ORDENAR VARIABLES SEGÚN EL ANÁLISIS PCA, REALIZAR BOOSTING, OBTENER REGLAS DEL MODELO C50
if(!require(C50)){
install.packages('C50', repos='http://cran.us.r-project.org')
library(C50)
}
trainy = as.factor(trainy)
modelo_clasificacion_C50 <- C50::C5.0(trainx, trainy,rules=TRUE,control = C5.0Control(noGlobalPruning = FALSE) )
summary(modelo_clasificacion_C50)
##
## Call:
## C5.0.default(x = trainx, y = trainy, rules = TRUE, control
## = C5.0Control(noGlobalPruning = FALSE))
##
##
## C5.0 [Release 2.07 GPL Edition] Mon Dec 13 19:37:07 2021
## -------------------------------
##
## Class specified by attribute `outcome'
##
## Read 612 cases (12 attributes) from undefined.data
##
## Rules:
##
## Rule 1: (77/1, lift 2.0)
## Sex = F
## RestingBP <= 148
## FastingBS <= 0
## ExerciseAngina = N
## -> class 0 [0.975]
##
## Rule 2: (40/3, lift 1.9)
## ChestPainType = NAP
## RestingBP <= 132
## MaxHR > 150
## -> class 0 [0.905]
##
## Rule 3: (72/8, lift 1.8)
## ChestPainType in {ATA, TA}
## MaxHR > 150
## -> class 0 [0.878]
##
## Rule 4: (272/46, lift 1.7)
## ST_Slope = Up
## -> class 0 [0.828]
##
## Rule 5: (50, lift 1.9)
## ChestPainType = ASY
## RestingBP <= 131
## FastingBS > 0
## -> class 1 [0.981]
##
## Rule 6: (23, lift 1.8)
## ChestPainType = ASY
## Cholesterol <= 197
## ExerciseAngina = Y
## -> class 1 [0.960]
##
## Rule 7: (60/2, lift 1.8)
## ChestPainType = ASY
## FastingBS > 0
## Oldpeak > 0.6
## -> class 1 [0.952]
##
## Rule 8: (75/3, lift 1.8)
## Sex = M
## ChestPainType = ASY
## Cholesterol > 227
## FastingBS <= 0
## ExerciseAngina = Y
## -> class 1 [0.948]
##
## Rule 9: (64/3, lift 1.8)
## Sex = M
## Oldpeak <= 0.3
## ST_Slope in {Down, Flat}
## -> class 1 [0.939]
##
## Rule 10: (9, lift 1.7)
## Sex = M
## ChestPainType = ASY
## RestingBP <= 126
## MaxHR > 146
## MaxHR <= 160
## ST_Slope = Up
## -> class 1 [0.909]
##
## Rule 11: (8, lift 1.7)
## ChestPainType = ASY
## RestingBP <= 126
## ExerciseAngina = N
## Oldpeak > 0.4
## ST_Slope = Up
## -> class 1 [0.900]
##
## Rule 12: (340/67, lift 1.5)
## ST_Slope in {Down, Flat}
## -> class 1 [0.801]
##
## Default class: 1
##
##
## Evaluation on training data (612 cases):
##
## Rules
## ----------------
## No Errors
##
## 12 49( 8.0%) <<
##
##
## (a) (b) <-classified as
## ---- ----
## 260 33 (a): class 0
## 16 303 (b): class 1
##
##
## Attribute usage:
##
## 100.00% ST_Slope
## 48.69% ChestPainType
## 38.24% FastingBS
## 35.62% Sex
## 29.90% ExerciseAngina
## 27.12% RestingBP
## 21.24% Oldpeak
## 19.77% MaxHR
## 16.01% Cholesterol
##
##
## Time: 0.0 secs
Explicar reglas:
predicted_model <- predict( modelo_clasificacion_C50, testx, type="class" )
print(sprintf("La precisión del modelo es: %.4f %%",100*sum(predicted_model == testy) / length(predicted_model)))
## [1] "La precisión del modelo es: 85.2941 %"
Vamos a realizar diferentes estudios gráficos para analizar las distintas variables del modelo y las relaciones entre ellas.
Para ello, diferenciaremos entre los tipos de variables continuas y discretas para su análisis y sí fuera necesario transformaremos las variables para su estudio más eficiente.
head(heart)
## Age Sex ChestPainType RestingBP Cholesterol FastingBS RestingECG MaxHR
## 1 40 M ATA 140 289 0 Normal 172
## 2 49 F NAP 160 180 0 Normal 156
## 3 37 M ATA 130 283 0 ST 98
## 4 48 F ASY 138 214 0 Normal 108
## 5 54 M NAP 150 195 0 Normal 122
## 6 39 M NAP 120 339 0 Normal 170
## ExerciseAngina Oldpeak ST_Slope HeartDisease Age_nor Age_dist
## 1 N 0.0 Up 0 -0.51020408 (0-40]
## 2 N 1.0 Flat 1 -0.14285714 (40,60]
## 3 N 0.0 Up 0 -0.63265306 (0-40]
## 4 Y 1.5 Flat 1 -0.18367347 (40,60]
## 5 N 0.0 Up 0 0.06122449 (40,60]
## 6 N 0.0 Up 0 -0.55102041 (0-40]
Variables discretas:
library(ggplot2)
ggplot(data=heart,aes(x=Age_dist,fill=(factor(HeartDisease))))+geom_bar() + ggtitle("Enfermedad Cardiaca por grupo de edad(G1)") + labs(x="Edad", colour= "HeartDisease")
ggplot(data=heart,aes(x=Sex,fill=factor(HeartDisease)))+geom_bar() + ggtitle("Enfermedad Cardiaca por sexo(G2)") + labs(x="sexo", colour= "HeartDisease")
ggplot(data=heart,aes(x=ChestPainType,fill=factor(HeartDisease)))+geom_bar() + ggtitle("Enfermedad Cardiaca por ChestPainType(G3)") + labs(x="ChestPainType", colour= "HeartDisease")
ggplot(data=heart,aes(x=RestingECG,fill=factor(HeartDisease)))+geom_bar() + ggtitle("Enfermedad Cardiaca por RestingECG(G4)") + labs(x="RestingECG", colour= "HeartDisease")
# ExerciseAngina & HeartDisease
ggplot(data=heart,aes(x=ExerciseAngina,fill=factor(HeartDisease)))+geom_bar() + ggtitle("Enfermedad Cardiaca por ExerciseAngina(G5)") + labs(x="ExerciseAngina", colour= "HeartDisease")
# ST_Slope & HeartDisease
ggplot(data=heart,aes(x=ST_Slope,fill=factor(HeartDisease)))+geom_bar() + ggtitle("Enfermedad Cardiaca por ST_Slope(G6)") + labs(x="ST_Slope", colour= "HeartDisease")
# FastingBS & HeartDisease
ggplot(data=heart,aes(x=FastingBS,fill=factor(HeartDisease)))+geom_bar() + ggtitle("Enfermedad Cardiaca por FastingBS(G7)") + labs(x="FastingBS", colour= "HeartDisease")
Variables continuas:
EStudiamos la relación entre la variable edad y colesterol, ya que hemos estudiado su relación anteriormente.
# Coresterol & Sexo
ggplot(heart, aes(x =heart$Age, y = heart$Cholesterol)) + geom_point()+
geom_smooth(method = "loess")
## Warning: Use of `heart$Age` is discouraged. Use `Age` instead.
## Warning: Use of `heart$Cholesterol` is discouraged. Use `Cholesterol` instead.
## Warning: Use of `heart$Age` is discouraged. Use `Age` instead.
## Warning: Use of `heart$Cholesterol` is discouraged. Use `Cholesterol` instead.
## `geom_smooth()` using formula 'y ~ x'
Estudiamos el resto de variables continuas, en relación con su edad y el riesgo o no de sufrir una enfermedad cardíaca:
ggplot(heart, aes(RestingBP, Age, colour = HeartDisease)) +
geom_point()+ ggtitle("AÑADIR TITULO GRÁFICO")
ggplot(heart, aes(Cholesterol, Age, colour = HeartDisease)) +
geom_point()+ ggtitle("AÑADIR TITULO GRÁFICO")
ggplot(heart, aes(MaxHR, Age, colour = HeartDisease)) +
geom_point() + ggtitle("AÑADIR TITULO GRÁFICO")
ggplot(heart, aes(Oldpeak, Age, colour = HeartDisease)) +
geom_point() + ggtitle("AÑADIR TITULO GRÁFICO")
COMENTAR CONCLUSIONES DE CADA GRÁFICO y añadir más gráficos si fuera necesario
añadir # Recursos
añadir